﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Net;
using System.Net.Sockets;
using Matrix_ClassLibrary;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Windows.Forms;
namespace LTTT_Client
{
    class ConnectionClient
    {
        // Delegate Event được dùng để gọi một phương thức nào đó trong class Recevier
        public delegate void DoSomeThingDelegate();
        public event DoSomeThingDelegate ProcessReceive;
        public event DoSomeThingDelegate UpdateStatusConnect;

        // biến toàn cục matrix 
        public Matrix matrix;

        byte[] data = new byte[2048];
        Socket client;
        public string HeaderMessage = string.Empty;
        public string ReceiveMessage;

        // Contructor tạo một liên kết với tham số đầu vào là IP server
        public ConnectionClient(string IP)
        {
            
                IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(IP), 30000);
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                client.BeginConnect(ipe, new AsyncCallback(CallConnect), client);
                matrix = null;
            
        }
        ~ConnectionClient()
        {
            client.Close();
        }

        // Hàm bất đồng bộ được dùng để kết nối server
        public void CallConnect(IAsyncResult air)
        {
            try
            {
                client = (Socket)air.AsyncState;
                client.EndConnect(air);
                client.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
            }
            catch
            {
                MessageBox.Show("Kết nối không thành công. Xin vui lòng kiểm tra lại!", "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
                UpdateStatusConnect();
            }
        }

        // Hàm bất đồng bộ nhận dữ liệu về
        // Nếu header = 0 : đó là matrix
        // Nếu header = 1 : đó là V gửi tới
        private void ReceiveData(IAsyncResult air)
        {
                client = (Socket)air.AsyncState;
                int rc = client.EndReceive(air);
                this.HeaderMessage = Encoding.UTF8.GetString(data, 0, 1);
            //Nếu header là 0, đó là matrix
                if (this.HeaderMessage == "0")
                {

                    //ReceiveMatrix();
                    MemoryStream stream = new MemoryStream(data, 1, data.Length - 1);
                    IFormatter formater = new BinaryFormatter();
                    // Deserialize matrix
                    matrix = (Matrix)formater.Deserialize(stream);
 
                }
                else
                    // Nếu là 1 ta sẽ đọc dữ liệu được từ server
                    ReceiveMessage = Encoding.UTF8.GetString(data, 1, rc - 1);
              
                ProcessReceive();
        }

        // Gửi dữ liệu vè server
        public void SendData(string message)
        {
            byte[] send = Encoding.UTF8.GetBytes(message);
            // bắt đầu quá trình gửi bất đồng bộ. gọi hàm SenData phía dưới
            client.BeginSend(send, 0, send.Length, SocketFlags.None, new AsyncCallback(SendData), client);
        }
        // Hàm Bất đồng bộ gửi dữ liệu về
        private void SendData(IAsyncResult air)
        {
            client = (Socket)air.AsyncState;
            client.EndSend(air); // Kết thúc quá trình gửi
            // Bắt đầu quá trình nhận bất đồng bộ
            client.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveData), client);
        }
    }
        
}
